package br.org.acessobrasil.processoacessibilidade.bo;

import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import br.org.acessobrasil.ases.regras.RegrasHardCodedEmag;
import br.org.acessobrasil.padrao.LinguagemPagina;
import br.org.acessobrasil.processoacessibilidade.dao.FormularioDao;
import br.org.acessobrasil.processoacessibilidade.dao.PaginaDao;
import br.org.acessobrasil.processoacessibilidade.vo.FormularioPro;
import br.org.acessobrasil.processoacessibilidade.vo.JobPro;
import br.org.acessobrasil.processoacessibilidade.vo.LinguagemProgramacaoPro;
import br.org.acessobrasil.processoacessibilidade.vo.PaginaPro;

public class Analista {
	private static Pattern patForm = Pattern.compile("<form[^>]*>",Pattern.CASE_INSENSITIVE);
	private static Pattern patInput = Pattern.compile("<input[^>]*>",Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
	private static Pattern patTextArea = Pattern.compile("<textarea[^>]*>",Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
	private static Pattern patSelect = Pattern.compile("<select[^>]*>",Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
	private static RegrasHardCodedEmag regras = new RegrasHardCodedEmag();
	
	private static FormularioDao formularioDao;
	private static PaginaDao paginaDao;
			
	private static Logger logger = Logger.getLogger(Analista.class);

	public void verificarFormulario(PaginaPro pagina,JobPro job) throws Exception{
		if(pagina.getCodOriginal()==null){
			System.err.println("AVISO: Analista: O codigo da pagina "+pagina.getUrl()+" esta nulo.");
			return;
		}
		Matcher mat = patForm.matcher(pagina.getCodOriginal());
		boolean achouFormulario = false;
		while(mat.find()){
			achouFormulario = true;
			String tagForm = mat.group();
			String action = regras.getAtributo(tagForm, "action");
			//encontrar o fim da tag
			if(pagina.getCodOriginal()==null){
				System.err.println("AVISO: Analista: O codigo da pagina "+pagina.getUrl()+" esta nulo.");
				return;
			}
			if(mat==null){
				System.err.println("AVISO: Analista: O objeto 'mat' esta nulo.");
				return;
			}
			int f = pagina.getCodOriginal().indexOf("</form>",mat.end());
			int f2 = pagina.getCodOriginal().indexOf("</FORM>",mat.end());
			if(f==-1)f=f2;
			if(f!=-1 && f2!=-1) f=f<f2?f:f2;
			if(f==-1)continue;		
			
			String conteudoForm = pagina.getCodOriginal().substring(mat.end(),f);
			
			ArrayList<String> campoNome = new ArrayList<String>();
			FormularioPro formulario;
			//extrair os campos
			Matcher matCampo = patInput.matcher(conteudoForm);
			while(matCampo.find()){
				String name = regras.getAtributo(matCampo.group(), "name");
				campoNome.add(name);
			}
			matCampo = patSelect.matcher(conteudoForm);
			while(matCampo.find()){
				String name = regras.getAtributo(matCampo.group(), "name");
				campoNome.add(name);
			}
			matCampo = patTextArea.matcher(conteudoForm);
			while(matCampo.find()){
				String name = regras.getAtributo(matCampo.group(), "name");
				campoNome.add(name);
			}
			//ordenar os campos por nome
			Collections.sort(campoNome);
			logger.info("campos encontrados...");
			String campos="";
			for(String c:campoNome){
				campos +=c + "|";
			}
			try{
				URL url =new URL(new URL(pagina.getUrl()),action);
				action = url.toString();
				formulario = formularioDao.find(action, campos);
				if(formulario==null){
					formulario = new FormularioPro();
					formulario.setAction(action);
					formulario.setCampos(campos);
					logger.info("Salvando o formulario no banco...");
					formularioDao.create(formulario);
				}
				pagina = paginaDao.loadFormularios(pagina);
				if(!pagina.getListaFormulario().contains(formulario)){
					pagina.getListaFormulario().add(formulario);
				}
			}catch(Exception e){
				logger.error("Erro ao trabalhar com os daos" , e);
			}
		}
		if(achouFormulario){
			logger.info("Achou formulario(s) em... "+pagina.getUrl());
			paginaDao.update(pagina);
		}else{
			logger.info("Nao achou formulario(s) em... "+pagina.getUrl());
		}
	}
	
	/**
	 * verifica se a linguagem existe no banco, caso nao exista cria
	 * @param url
	 * @return o id da linguagem
	 */
	public Long verificarLinguagem(String url){
		try {
			String linguagem = LinguagemPagina.getLinguagemUrl(url);
			LinguagemProgramacaoPro lp = Coordenador.getLinguagemProgramacaoDao().find(linguagem.trim());
			if (lp==null)	{
				lp= new LinguagemProgramacaoPro();
				lp.setNomeLinguagem(linguagem);
				Coordenador.getLinguagemProgramacaoDao().create(lp);
				lp=Coordenador.getLinguagemProgramacaoDao().find(lp.getNomeLinguagem());
			}
			return 1L;//lp.getIdLinguagem();
		}catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}

	public static FormularioDao getFormularioDao() {
		return formularioDao;
	}
	public static void setFormularioDao(FormularioDao formularioDao) {
		Analista.formularioDao = formularioDao;
	}
	
	public static void setPaginaDao(PaginaDao paginaDao) {
		Analista.paginaDao = paginaDao;
	}
}
